﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Pap.Data;
using Pap.Data.Abstraction.Utils;
using Pap.Web.Utils;

namespace Pap.Web.Modules.Administration.ViewModel
{
    /// <summary>
    /// 
    /// </summary>
    public class LookUpManagerViewModel : IViewModel
    {
        /// <summary>
        /// 
        /// </summary>
        ILookUpRepository _Repo;

        /// <summary>
        /// Initializes a new instance of the <see cref="LookUpManagerViewModel"/> class.
        /// </summary>
        /// <param name="repository">The repository.</param>
        public LookUpManagerViewModel(ILookUpRepository repository)
        {
            _Repo = repository;
        }

        /// <summary>
        /// Gets all.
        /// </summary>
        /// <param name="tableName">Name of the table.</param>
        /// <returns></returns>
        public IEnumerable<ILookUpEntity> GetAll(string tableName)
        {
            return _Repo.GetAll(tableName);
        }

        /// <summary>
        /// Gets all.
        /// </summary>
        /// <param name="tableName">Name of the table.</param>
        /// <param name="parentTableName">Name of the parent table.</param>
        /// <param name="fkName">Name of the fk.</param>
        /// <returns></returns>
        public IEnumerable GetAll(string tableName, string parentTableName, string fkName)
        {
            IEnumerable<ILookUpEntity> table = _Repo.GetAll(tableName);
            IEnumerable<ILookUpEntity> parentTable = _Repo.GetAll(parentTableName);

            List<LookUpEntityWithParent> result = new List<LookUpEntityWithParent>();
            foreach (var child in table)
            {
                Guid parentID = (Guid)_Repo.GetProperty(child, fkName).GetValue(child, null);
                string pName = parentTable.SingleOrDefault(e => e.ID == parentID).Name;
                result.Add(new LookUpEntityWithParent
                {
                    ID = child.ID,
                    Name = child.Name,
                    PID = parentID,
                    PName = pName,
                });
            }
            return result;
        }

        /// <summary>
        /// Inserts the specified table name.
        /// </summary>
        /// <param name="tableName">Name of the table.</param>
        /// <param name="name">The name.</param>
        public void Insert(string tableName, string name)
        {
            using (IUnitOfWork transaction = this.GetInstance<IUnitOfWork>())
            {
                _Repo.Insert(tableName, name);
                transaction.Commit();
            }
        }

        /// <summary>
        /// Inserts the specified table name.
        /// </summary>
        /// <param name="tableName">Name of the table.</param>
        /// <param name="name">The name.</param>
        /// <param name="fkName">Name of the fk.</param>
        /// <param name="parentId">The parent id.</param>
        public void Insert(string tableName, string name, string fkName, Guid parentId)
        {
            using (IUnitOfWork transaction = this.GetInstance<IUnitOfWork>())
            {
                _Repo.Insert(tableName, name, fkName, parentId);
                transaction.Commit();
            }
        }

        /// <summary>
        /// Inserts the specified table name.
        /// </summary>
        /// <param name="tableName">Name of the table.</param>
        /// <param name="name">The name.</param>
        /// <param name="extraParams">The extra params.</param>
        public void Insert(string tableName, string name, Dictionary<string, string> extraParams)
        {
            using (IUnitOfWork transaction = this.GetInstance<IUnitOfWork>())
            {
                _Repo.Insert(tableName, name, extraParams);
                transaction.Commit();
            }
        }

        /// <summary>
        /// Updates the specified table name.
        /// </summary>
        /// <param name="tableName">Name of the table.</param>
        /// <param name="id">The id.</param>
        /// <param name="name">The name.</param>
        public void Update(string tableName, Guid id, string name)
        {
            using (IUnitOfWork transaction = this.GetInstance<IUnitOfWork>())
            {
                _Repo.Update(tableName, id, name);
                transaction.Commit();
            }
        }

        /// <summary>
        /// Updates the specified table name.
        /// </summary>
        /// <param name="tableName">Name of the table.</param>
        /// <param name="id">The id.</param>
        /// <param name="name">The name.</param>
        /// <param name="fkName">Name of the fk.</param>
        /// <param name="parentId">The parent id.</param>
        public void Update(string tableName, Guid id, string name, string fkName, Guid parentId)
        {
            using (IUnitOfWork transaction = this.GetInstance<IUnitOfWork>())
            {
                _Repo.Update(tableName, id, name, fkName, parentId);
                transaction.Commit();
            }
        }

        /// <summary>
        /// Deletes the specified table name.
        /// </summary>
        /// <param name="tableName">Name of the table.</param>
        /// <param name="entities">The entities.</param>
        public void Delete(string tableName, List<Guid> entities)
        {
            using (IUnitOfWork transaction = this.GetInstance<IUnitOfWork>())
            {
                _Repo.DeleteAll(tableName, entities);
                transaction.Commit();
            }
        }

        /// <summary>
        /// 
        /// </summary>
        class LookUpEntityWithParent
        {
            /// <summary>
            /// Gets or sets the ID.
            /// </summary>
            /// <value>
            /// The ID.
            /// </value>
            public Guid ID { get; set; }
            /// <summary>
            /// Gets or sets the name.
            /// </summary>
            /// <value>
            /// The name.
            /// </value>
            public string Name { get; set; }
            /// <summary>
            /// Gets or sets the PID.
            /// </summary>
            /// <value>
            /// The PID.
            /// </value>
            public Guid PID { get; set; }
            /// <summary>
            /// Gets or sets the name of the P.
            /// </summary>
            /// <value>
            /// The name of the P.
            /// </value>
            public string PName { get; set; }
        }
    }
}
